package com.tansun.ruledata.data.service.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.drools.core.util.StringUtils;
import org.kie.api.KieBase;
import org.kie.api.io.ResourceType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.tansun.rule.api.impl.RuleServiceImpl;
import com.tansun.rule.common.KieBaseFactory;
import com.tansun.rule.common.ResourceContentInfo;
import com.tansun.rule.common.RuleModelTypeEnum;
import com.tansun.rule.config.AppConfiguration;
import com.tansun.rule.exception.RuleInvokeException;
import com.tansun.rule.pojo.EnterPoint;
import com.tansun.rule.utils.AppCacheInfo;
import com.tansun.rule.utils.HttpUtils;
import com.tansun.rule.utils.MClass;
import com.tansun.ruledata.data.entity.DeployReferenceData;
import com.tansun.ruledata.data.entity.DeployVersionInfo;
import com.tansun.ruledata.data.service.BussinessSynchService;
import com.tansun.ruledata.data.service.RuleDeployResourceService;
import com.tansun.ruledata.data.service.RuleResourceLoadService;
import com.tansun.ruledata.sessionpool.RuleDataPooledSessionFactory;
import com.tansun.ruledata.sessionpool.SessionDataPool;


@Service
public class RuleResourceLoadServiceImpl implements RuleResourceLoadService {

	private final Logger log = LoggerFactory.getLogger(this.getClass());
	

	@Autowired
	private RuleDeployResourceService  ruleDeployResourceService;

    @Autowired
	private BussinessSynchService bussinessSynchService;
	@Autowired
	private  RuleServiceImpl ruleService;
	
	@Override
	public void loadEnterPoint(String ruleObjectName,String invokePoint) {
		Map<String,EnterPoint> eMap =ruleDeployResourceService.findEnterPoint(ruleObjectName,invokePoint);
		if (eMap != null && !eMap.isEmpty()){
			Map<String,EnterPoint> pMap = AppConfiguration.ruleEnterMap.get(ruleObjectName);
			if (pMap == null){
				pMap  = new  HashMap<>();
			}
			for (String key :eMap.keySet()){
				pMap.put(key, eMap.get(key));
			}
			AppConfiguration.ruleEnterMap.put(ruleObjectName, pMap);
		}	

	}

	@Override
	public void loadEnterPointDeployResource(String ruleObjectName, String invokePoint) throws Exception {
		// TODO Auto-generated method stub
		//Map<String,Collection<RuleVersionVO>>	conMap=this.ruleVersionDAO.findDeployRuleVersion(ruleObjectName,invokePoint);
		//I9用
		Map<String,Collection<DeployVersionInfo>>	conMap=this.ruleDeployResourceService.findLatestRuleVersion(ruleObjectName,invokePoint);
		//中信卡核心
//		Map<String,Collection<RuleVersionVO>>	conMap=this.businessDBDao.findDeployRuleVersion_new(ruleObjectName,invokePoint);
		
		if (conMap == null || conMap.isEmpty()){
			throw new RuleInvokeException("Drl文件加载失败！");
		}
		Collection<DeployVersionInfo>  list= conMap.get(invokePoint);
		String  fundrl =AppConfiguration.funcMap.get(ruleObjectName);
		if (fundrl  == null) {
		   this.loadRuleFunctionDrl(ruleObjectName);
		   fundrl =AppConfiguration.funcMap.get(ruleObjectName);
		}
		if (!StringUtils.isEmpty(fundrl)) {
			DeployVersionInfo  ruVer = new  DeployVersionInfo();
			ruVer.setContont(fundrl);
			ruVer.setRuleContent(fundrl);
			ruVer.setModelType(RuleModelTypeEnum.FunctionParam.code);
			list.add(ruVer);
		}
		RuleDataPooledSessionFactory psf = RuleDataPooledSessionFactory.buildPooledSessionFactoryByDataRuleProj(list,invokePoint);
		SessionDataPool sessionPool = new SessionDataPool(psf);
		AppConfiguration.AppRuleProjDataPools.put(ruleObjectName+"_"+invokePoint, sessionPool);
	} 
	
	@Override
	public void loadDeployedRuleFlow(String ruleObjectName, String invokePoint) throws Exception {
		List<DeployVersionInfo> list = this.ruleDeployResourceService.findDeployedRuleFlow(ruleObjectName, invokePoint);
		RuleDataPooledSessionFactory psf = RuleDataPooledSessionFactory.buildPooledSessionFactoryByDataRuleProj(list,invokePoint);

		SessionDataPool sessionPool = new SessionDataPool(psf);
	
		AppConfiguration.AppRuleProjDataPoolsForJob.put(ruleObjectName+"_"+invokePoint, sessionPool);
	}

	public void loadProjectDataMapping(String ruleObjectName) {
		Map<String, MClass> metaMap=ruleDeployResourceService.findMapping(ruleObjectName);
		AppConfiguration.RuleProjMetaMap.put(ruleObjectName, metaMap);
	}

	

	@Override
	public void sycCluster(final String ruleObjectName, final String invokePoint) {
		/*Properties pro = new Properties();
		try {
			pro.load(this.getClass().getClassLoader().getResourceAsStream("DeployConfig.properties"));
		} catch (IOException e) {
			log.error("获取集群部署信息失败", e);
			return;
		}
		String hosts = pro.getProperty("cluster.hosts");
		if(hosts==null||"".equals(hosts)){
			return;
		}
		String list[] = hosts.split(",");*/
		List<String> list = this.ruleDeployResourceService.findClusterHosts("rule_cluster_hostsk");
		ExecutorService pool = Executors.newCachedThreadPool();
		for(final String ser:list){
			pool.execute(new Runnable() {
				
				@Override
				public void run() {
					try {
						String res = HttpUtils.deployRuleDataPackage("http://"+ser+"/rule-executer/ruledeploy/sycDataRule", invokePoint,
								"admin", "thepass","", ruleObjectName);
						if (!"Yes".equals(res)) {
							log.error("同步服务器失败:"+ser+","+res);
						}
					}catch (Exception e) {
						log.error("同步服务器报错:"+ser, e);
					}
				}
			});
		}
		pool.shutdown();
	}

	@Override
	public void loadProjectRefeDrl(String ruleObjectName,String enterPoint) {
		  Map<String,String>  map  = this.ruleDeployResourceService.findRuleReleByProjectCode(ruleObjectName);
		  AppConfiguration.ruleRefMap.put(ruleObjectName+"_"+enterPoint, map);
	}

	//初始化决策树模型引用
	private void buildKieBase(String projectCode,String enterPoint,String timeStamp) {
		String  funcDrl = AppConfiguration.funcMap.get(projectCode+"_"+timeStamp);
		 Map<String,String>   drlMap  = AppConfiguration.ruleRefMap.get(projectCode+"_"+timeStamp);
        if (drlMap==null || AppConfiguration.ruleRefMap ==null || AppConfiguration.ruleRefMap.isEmpty()) {
        	return;
        }
        Map<String,KieBase>  kieMap = AppCacheInfo.kieMap.get(projectCode+"_"+timeStamp);
        kieMap = null;//清楚历史缓存对象
        ResourceContentInfo  resContent  = null;
		for (Entry<String, String> entry : drlMap.entrySet()) {
			String ruleKey = entry.getKey();
	        if (kieMap == null) {
	        	kieMap = new HashMap<>();
	        	AppCacheInfo.kieMap.put(projectCode+"_"+timeStamp, kieMap);
	        }
	        List<ResourceContentInfo> drlList = new ArrayList<ResourceContentInfo>();
	        String drlContent =drlMap.get(ruleKey);
	        if (!StringUtils.isEmpty(drlContent))
	        {        
	        	resContent  = new  ResourceContentInfo(drlContent, ResourceType.DRL);
	        	drlList.add(resContent);
	        
	        }
	        if (!StringUtils.isEmpty(funcDrl)) {
	        	resContent  = new  ResourceContentInfo(funcDrl,ResourceType.DRL);
	        	drlList.add(resContent);
	        }        	
	        //KieBase kieBase  = kieHelper.build(ConsequenceExceptionHandlerOption.get(RuleConsequenceExceptionHandler.class));
	        KieBase kieBase= KieBaseFactory.getInstance().createKieBase(drlList);
	        kieMap.put(ruleKey, kieBase);
		}
	}
	@Override
	public void loadProjectPmml(String ruleObjectName) {
		Map<String,String>  map  = this.ruleDeployResourceService.findPmmlByProjectCode(ruleObjectName);
		AppConfiguration.PmmlMap.put(ruleObjectName, map);
	}
	

	
	public void loadProjectPmmlRefData(String ruleObjectName) {
		Map<String,Map<String, DeployReferenceData>> pmmlRefParamMap  = this.ruleDeployResourceService.findPmmlRefByProjectCode(ruleObjectName);
		AppConfiguration.PmmlRefParamMap.put(ruleObjectName, pmmlRefParamMap);
	}
	

	public  void  loadRuleFunctionDrl(String ruleObjectName) {
        AppConfiguration.funcMap.put(ruleObjectName, this.ruleDeployResourceService.findEffectiveFunc(ruleObjectName));        
	}

   /**
    * 加载项目信息
    * PMML模型对应的变量
    * PMML模型
    * 项目引用规则
    * @param ruleObjectName
    * @param timeStamp
    */
	public void loadProjectPmmlFuncDrl(String ruleObjectName,String enterPonit, String timeStamp) {
		AppConfiguration.funcMap.put(ruleObjectName+"_"+timeStamp, this.bussinessSynchService.getEffectiveFunc(ruleObjectName,timeStamp));
		
		Map<String,String>  map1  = this.bussinessSynchService.findPmmlByProjectCode(ruleObjectName,timeStamp);
		AppConfiguration.PmmlMap.put(ruleObjectName, map1);
		  
		Map<String,Map<String, DeployReferenceData>> pmmlRefParamMap  = this.bussinessSynchService.findPmmlRefByProjectCode(ruleObjectName,timeStamp);
		AppConfiguration.PmmlRefParamMap.put(ruleObjectName, pmmlRefParamMap);
					
		Map<String,String> map2 = this.bussinessSynchService.findRuleReleByProjectCode(ruleObjectName,timeStamp);
		AppConfiguration.ruleRefMap.put(ruleObjectName+"_"+timeStamp, map2);
		buildKieBase(ruleObjectName,enterPonit,timeStamp);
	}


}
